package main;// File Name:  	    Game.java

// Author:       	ChenXu ����
// Student Number:  3012218109
// Class:           Class 2

// Description:     This is a ball game which vanish 5 balls in line,and there is some special balls
// 					such: wild ball match all colors of ball,bomb can disappear all same color
//                  ****This is an ViewController class used to control Model and View****
// Future Improvements: ----score animation
//                      ----a special ball to remove all one line
// 						----a special ball to remove 3*3 balls arounda the center ball

import javafx.animation.FadeTransition;
import javafx.animation.Interpolator;
import javafx.animation.ParallelTransition;
import javafx.animation.ScaleTransition;
import javafx.animation.ScaleTransitionBuilder;
import javafx.animation.SequentialTransition;
import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.SceneBuilder;
import javafx.scene.control.Button;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.StackPaneBuilder;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.Duration;
import main.reversi.model.Holder;
import main.reversi.model.ReversiModel;
import main.reversi.ui.Piece;
import main.reversi.ui.Square;

public class game extends Application {
	
  public static void main(String[] args) {
    launch(args);
  }
  
  public static ReversiModel model = new ReversiModel();
 
  public void start(Stage primaryStage) {
	  //a mask used to hide destination ball which appears immediately when game is over
	  //and disappears after animation
	   final Text over = new Text("Game over");
	   final Rectangle mask = new Rectangle(630,630);
	   mask.setOpacity(0.5);
	   
	  final BorderPane scene = new BorderPane();
	  
	  //left of BorderOane
	  VBox left = new VBox(10);
	  
	  Text text = new Text("score:");
	  text.setFont(new Font(20));
	  Text scoreLabel = new Text();
	  scoreLabel.setFont(new Font(20));
	  Button restart = new Button("restart");
	  
	  scoreLabel.textProperty().bind(ReversiModel.scoreProperty());
	  left.getChildren().addAll(text,scoreLabel,restart);
	  scene.setLeft(left);
	  
	  //center of borderPane
	  final AnchorPane ani = new AnchorPane();
	  ani.setPrefSize(630, 630);
	  ani.getChildren().add(tiles());
	  scene.setCenter(ani);


	  ani.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>(){
		  public void handle(MouseEvent t){
			  final int x = (int)t.getX()/70;
			  final int y = (int)t.getY()/70;


			  if(!model.play(x, y)){
				  //first time or
				  //game over
				  if(model.isFull()){
				  over.setFont(new Font(40));
				  over.setFill(Color.WHITE);
				  
				  scene.getChildren().addAll(mask,over);

				  over.setX(340);
				  over.setY(350);
				  mask.setX(80);
				  
				  over.setOpacity(0);
				  ScaleTransition bigger =  ScaleTransitionBuilder.create()
						  .node(over)
						  .fromX(1)
						  .fromY(1)
						  .toX(2)
						  .toY(2)
						  .build();
						  
				  
				  FadeTransition fadeTransition = new FadeTransition(Duration.millis(800), over);
				  ParallelTransition parall = new ParallelTransition(bigger,fadeTransition);
				  fadeTransition.setFromValue(0); 
				  fadeTransition.setToValue(1); 
				  parall.play( );
				  }
			  }
			  else{//second time
					  final Piece piece = new Piece(model.board[x][y].get());
					 
					  final Square sqr = new Square(Holder.SQUARE);
					  AnchorPane.setLeftAnchor(sqr, (double) (x*70));
					  AnchorPane.setTopAnchor(sqr,(double) (y*70));
					  ani.getChildren().add(sqr);
					  ani.getChildren().add(piece);

					  //show move animation
					  SequentialTransition seqT = new SequentialTransition ();
					  for(int i=0;i< model.path.length-1;i++){
						  TranslateTransition move = new TranslateTransition();
						  move.setInterpolator(Interpolator.LINEAR);
						  move.setDuration(Duration.millis(100));
						  move.setNode(piece);
						  move.setFromX((model.path[i]/9)*70+5);
						  move.setFromY((model.path[i]%9)*70+5);
						  move.setToX((model.path[i+1]/9)*70+5);
						  move.setToY((model.path[i+1]%9)*70+5);
						  seqT.getChildren().add(move);
					  }
					  seqT.play();
					  seqT.setOnFinished(new EventHandler<ActionEvent>(){
						  public void handle(ActionEvent t){			  
							  ani.getChildren().remove(sqr);
							  ani.getChildren().remove(piece);
							  ReversiModel.vanishWild(x, y);
							  model.oneturn();
						  
					  }
					  });	
				  	}

			  }
		  }
	  );
	  
	  
	  //right of borderPane
	  VBox right = new VBox(10);
	  Text text2 = new Text("next balls ");
	  text2.setFont(new Font(14));
	  Piece ball1 = new Piece();
	  Piece ball2 = new Piece();
	  Piece ball3 = new Piece();
	  
	  ball1.ownerProperty().bind(model.ball[0]);
	  ball2.ownerProperty().bind(model.ball[1]);
	  ball3.ownerProperty().bind(model.ball[2]);

      scene.setRight(right);
	  
	  right.getChildren().addAll(text2,ball1,ball2,ball3);
	  

	  //set alignments
	  left.setAlignment(Pos.CENTER);
	  left.setPrefWidth(80);
	  
	  right.setAlignment(Pos.CENTER_LEFT);
	  //button 'restart' pressed
	  restart.addEventHandler(MouseEvent.MOUSE_CLICKED,new EventHandler<MouseEvent>(){
		  public void handle(MouseEvent t){
			  ReversiModel.restart();
			  scene.getChildren().removeAll(over,mask);
		  }
	  });
	  
	  
	  //set the size of stage
	  int width = 800;
	  int height = 670;
      primaryStage.setScene(SceneBuilder.create()
    		.width(width)
    		.height(height)
            .root(scene)
            .build());
      primaryStage.setMaxHeight(height);
      primaryStage.setMaxWidth(width);
      primaryStage.setMinHeight(height);
      primaryStage.setMinWidth(width);

      primaryStage.show();
  }
  
 
  
  
  
  //build the board
  private Node tiles(){
	  System.out.println("-----creat tiles------");

	  final GridPane board = new GridPane();
	  
	  for(int i = 0;i < 9;i++ ){
		  for(int j = 0;j< 9;j++){
			  
			  Square square = new Square(i,j);
              final Piece piece = new Piece(i,j);
              final int tempx = i;
              final int tempy = j;
              square.ownerProperty().bind(model.back[i][j]);
              piece.ownerProperty().bind(model.board[i][j]);
              StackPane stack = StackPaneBuilder.create()
            		  .children(square,piece)
            		  .build();
              
              square.addEventHandler(MouseEvent.MOUSE_ENTERED_TARGET,new EventHandler<MouseEvent>(){
        		  public void handle(MouseEvent t){
                     model.light(tempx, tempy);
        		  }
        	  }); 
        
			  board.add(stack,i,j);
		  }
	  }
	
	  return board;
  }
  
 
}
